/*************************************************************
 * Title: Hibernate4Helper.java
 * Description: 
 * Author: Huang Shaobin
 * Email: huangshaobin@qtt.cn
 * CreateTime: Feb 11, 2013 10:53:38 AM
 * Copyright © 北京全天通信息咨询服务有限公司 All right reserved
 ************************************************************/
package snow.core.persistence.hibernate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 *
 */
public class Hibernate4Helper {

	public static interface OpenSessionCallback {

		void doCallback(SessionFactory sessionFactory, SessionHolder sessionHolder);

	}

	private static final Log log = LogFactory.getLog(HibernateHelper.class);

	public static void closeSession(boolean participate, boolean isAsyncStarted, SessionFactory sessionFactory) {
		if (!participate) {
			SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
			if (!isAsyncStarted) {
				log.debug("Closing Hibernate Session in Hibernate4Helper");
				SessionFactoryUtils.closeSession(sessionHolder.getSession());
			}
		}
	}

	public static void closeSession(Session session, SessionFactory sessionFactory) {
		SessionFactoryUtils.closeSession(session);
	}

	protected static Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
		try {
			Session session = sessionFactory.openSession();
			session.setFlushMode(FlushMode.MANUAL);
			return session;
		} catch (HibernateException ex) {
			throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
		}
	}

	public static boolean openSession(SessionFactory sessionFactory, boolean isAsyncDispatch, boolean applySessionBindingInterceptor,
			OpenSessionCallback openSessionCallback) {
		boolean participate = false;

		if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
			// Do not modify the Session: just set the participate flag.
			participate = true;
		} else {
			boolean isFirstRequest = !isAsyncDispatch;
			if (isFirstRequest || !applySessionBindingInterceptor) {
				log.debug("Opening Hibernate Session in Hibernate4Helper");
				Session session = openSession(sessionFactory);
				SessionHolder sessionHolder = new SessionHolder(session);
				TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
				openSessionCallback.doCallback(sessionFactory, sessionHolder);
			}
		}
		return participate;
	}

}
